﻿
/// <reference path="_namespace.js" />

/*****************************************************************************
Ajax library class definition. Kevin Robinson 2007.
For server use.
Class: ajax.data.Service
/*****************************************************************************/

ajax.lang.addNamespace("ajax.data");

//-----------------------------------------------------------------------------
ajax.data.Service = function(nothing, connectionString, tableName, primaryKeyName, method, data)
{      
    this.updateMethodName       = "Update"; // The name of the Web Service method to call to Update a data row
    this.deleteMethodName       = "Delete"; // The name of the web service method to call to delete a data row
    this.deletedRowMarker       = "RowDeleted"; // The marker applied by the web service to a row that has been deleted.
    
    this.nothing                = nothing;
    this.tableName              = tableName || "";
    this.primaryKeyName         = primaryKeyName || "ID";
    this.method                 = (method == this.updateMethodName || method == this.deleteMethodName) ? method : "";
    this.connectionString       = connectionString || "";
    this.data                   = data;    
    this._connection            = null;
    this._recordset             = null; 
    this.ignoreUpdateColumns    = [];
    this.sqlSelect              = "";
    this.sqlSelectWhere         = "";
    this.sqlSelectOrder         = "";
    this.sqlInsert              = "";
    this.sqlUpdate              = "";
    this.sqlDelete              = "";
    this.sql                    = "";
    this.primaryKeyPrefix       = "";

}
ajax.data.Service.prototype = 
{
    updateMethodName       : "Update", // The name of the Web Service method to call to Update a data row
    deleteMethodName       : "Delete", // The name of the web service method to call to delete a data row
    deletedRowMarker       : "RowDeleted", // The marker applied by the web service to a row that has been deleted.
    
    nothing                : null,
    tableName              : "",
    primaryKeyName         : "ID",
    method                 : "",
    connectionString       : "",
    data                   : null,    
    _connection            : null,
    _recordset             : null, 
    ignoreUpdateColumns    : [],
    sqlSelect              : "",
    sqlSelectWhere         : "",
    sqlSelectOrder         : "",
    sqlInsert              : "",
    sqlUpdate              : "",
    sqlDelete              : "",
    sql                    : "",
    primaryKeyPrefix       : ""
};

//-----------------------------------------------------------------------------
ajax.data.Service.prototype.createSqlCommands = function()
{ // Creates all update statements based on the data package, tableName and PrimaryKey name.
    this.sqlUpdate = this.createSqlUpdate();
    this.sqlInsert = this.createSqlInsert();
    this.sqlDelete = this.createSqlDelete();
}

//-----------------------------------------------------------------------------
ajax.data.Service.prototype.createSqlDelete = function()
{ // Creates a delete statement from the data structore passed (and tableName and primaryKeyName)
    var ret = "Delete " + this.tableName + " Where " + this.primaryKeyName + " = " + this.param(this.primaryKeyName);
    ret += ";Select " + this.param(this.primaryKeyName) + " as " + this.primaryKeyName + ", 'True' as " + this.deletedRowMarker;
    return ret;
}

//-----------------------------------------------------------------------------
ajax.data.Service.prototype.createSqlInsert = function()
{ // Creates an Insert statement from the data structore passed (and tableName and primaryKeyName)
    var vals = [];
    var selectCols = [];
    var updateCols = [];
    
    for (var name in this.data)
    {
        // Skip it?
        if (typeof(this.data[name]) == "Function")
            continue;
            
        selectCols.push(name);
        
        if (name == this.primaryKeyName || this.ignoreUpdateColumns.contains(name))
            continue;
        
        updateCols.push(name);
        vals.push(this.param(name));
    }
    var ret = "Insert Into " + this.tableName + "(" + updateCols + ") Values (" + vals + ")";
    // Select based on original statement as it may join tables etc
    ret += ";" + this.sqlSelect + " Where " + this.primaryKeyPrefix + this.primaryKeyName + " = Scope_Identity()";
    //ret += ";Select " + selectCols + " From " + this.tableName + " Where " + this.primaryKeyName + " = Scope_Identity()";
    return ret;
}
//-----------------------------------------------------------------------------
ajax.data.Service.prototype.createSqlUpdate = function()
{// Creates an update statement from the data structure passed (and tableName and primaryKeyName)    
    var vals        = [];   // The string values
    var selectCols  = [];   // The columns in the data
    for (var name in this.data) 
    {                
        // Skip it?
        if (typeof(this.data[name]) == "Function")
            continue;
        
        // Proper Column so push to column list
        selectCols.push(name);
        
        // DO NOT attempt to update the primary key
        if (name == this.primaryKeyName || this.ignoreUpdateColumns.contains(name))
            continue;
                    
        vals.push(name + " = " + this.param(name));
        
    }
    var ret = "Update " + this.tableName + " Set " + vals + " Where " + this.primaryKeyName + " = " + this.param(this.primaryKeyName);
    // Select based on original statement as it may join tables etc
    ret += ";" + this.sqlSelect + " Where " + this.primaryKeyPrefix + this.primaryKeyName + " = " + this.param(this.primaryKeyName); 
    //ret += ";Select " + selectCols + " From " + this.tableName + " Where " + this.primaryKeyName + " = " + this.param(this.primaryKeyName);
    return ret;    
}

//-----------------------------------------------------------------------------
ajax.data.Service.prototype.param = function(sName)
{
    var arr = sName.split(".");
    sName = arr.pop(); // last bit please
    var val = this.data[sName];        
    var type = ajax.lang.getType(val);
    var ret  = "";    
    switch (type)
    {
        case "number":
            ret = " " + val + " ";
            break;
        case "boolean":
            ret = " " + (val ? 1 : 0) + " ";
            break;            
        case "string":
            ret = " '" + val.replace("'", "''") + "' ";
            break;
        default:   
            ret = " '" + val + "' "                     
            break;            
    }
    return ret;
}

//-----------------------------------------------------------------------------
ajax.data.Service.prototype.getRecordset = function()
{
    if (!this._recordset)
    {
        this._recordset = Server.CreateObject("ADODB.Recordset");
        this._recordset.CursorLocation = 3; // adUseClient
    }
    return this._recordset;
}

//-----------------------------------------------------------------------------
ajax.data.Service.prototype.getConnection = function()
{
    if (!this._connection)
    {
        this._connection = Server.CreateObject("ADODB.Connection");
        this._connection.Open(this.connectionString);
    }        
    return this._connection;
}

//-----------------------------------------------------------------------------
ajax.data.Service.prototype.execute = function()
{ // If the Update, Insert & Delete commands are not set - this method will auto create a best guess!
  // This method returns a DISCONNECTED recordset (which is this objects .getRecordset() instance).
    this.sql = "";   
    if (this.method == this.updateMethodName)
    {
        if (this.param(this.primaryKeyName) > 0)
            this.sql = this.sqlUpdate || this.createSqlUpdate();
        else
            this.sql = this.sqlInsert || this.createSqlInsert(); 
    }
    else if (this.method == this.deleteMethodName)
        this.sql = this.sqlDelete || this.createSqlDelete();
    else
        this.sql = this.sqlSelect + " " + (this.sqlSelectWhere ? "Where " + this.sqlSelectWhere : "") + " " + (this.sqlSelectOrder ? "Order By " + this.sqlSelectOrder : "")
        
    this.getRecordset().Open(this.sql, this.getConnection(), 3, 1);  // adOpenStatic, adLockReadOnly
    if (this.method != "")
        this._recordset = this.getRecordset().NextRecordset();
        
    this.getRecordset().ActiveConnection = this.nothing;        // disconnect rs (Notice we use the nothing value passed to us)    
    return this.getRecordset();
}

//-----------------------------------------------------------------------------
ajax.data.Service.prototype.dispose = function()
{
    if (this._recordset)
    {
        this._recordset.Close();
        this._recordset = this.nothing;
    }
    if (this._connection)
    {
        this._connection.Close();
        this._connection = this.nothing;
    }
}

//-----------------------------------------------------------------------------
ajax.data.Service.cast = function(obj)
{///<returns type="ajax.data.Service"/>
    return obj;            
}
